# -*- coding: utf-8 -*-

"""
Various graphical effects for transitions using pygame.

"""

import pygame

import pyknicpygame
# from pyknicpygame import pyknic
# from pyknic import context
# from pyknic.context import transitions


# # ----------------------------------------------------------------------------
# # ----------------------------------------------------------------------------
# slide dx, dy
# slide in
# slide out
# slide from/to any point
# fade

# delete squares
# flip squares
# explode squares
# implode squares
# resolve squares
# fly through sqares
# fall down squares

# slide stripe (random)
# jalousie (flip stipe)
# delete stripe

# melt down

# zoom in (and fade)
# fly through

# rotate, one corner fixed, falling image
# rotate outwarts, both top corners fixed, split up in middle
# rotate and zoom out/in

# blizzard (turn white for a moment)

# fade using a template


# ------------------------------------------------------------------------------


class Slide(pyknicpygame.pyknic.context.transitions.TransitionEffect):
    """
    Sliding effect.
    """

    LEFT = (-1, 0)
    RIGHT = (1, 0)
    DOWN = (0, 1)
    UP = (0, -1)

    def __init__(self, duration, distance, direction=LEFT, \
                                                move_old=True, move_new=True):
        """
        .. todo:: make it an exception if both move_old and move_new are False
        """
        pyknicpygame.pyknic.context.transitions.TransitionEffect.__init__(self)
        self.current_time = duration
        dirx, diry = direction
        self.dir_x = dirx
        self.dir_y = diry
        
        self.posx = 0
        self.posy = 0
        self.speed = distance / duration
        self.distance = distance
        self.duration = duration
        self.move_old = move_old
        self.move_new = move_new
        # TODO:  make this an exception!
        assert move_old or move_new, "moving neither is not allowd" 
        self._old_surf = None
        self._new_surf = None
        
    def enter(self):
        self.current_time = self.duration
        self.posx = 0
        self.posy = 0
        
    def think(self, delta_time):
        self.posx += self.speed * self.dir_x * delta_time
        self.posy += self.speed * self.dir_y * delta_time
        self.current_time -= delta_time
        if self.current_time > 0:
            return False
        return True # done
        
    def draw(self, screen, old_context, new_context):
        screen_rect = screen.get_rect()
        old_rect = screen_rect.copy()
        new_rect = screen_rect.copy()
        
        if not self._old_surf:
            self._old_surf = screen.copy()
        self._old_surf.fill((0, 0, 0, 0))
        
        if not self._new_surf:
            self._new_surf = screen.copy()
        self._new_surf.fill((0, 0, 0, 0))
        
        old_context.draw(self._old_surf)
        new_context.draw(self._new_surf)
        
        if self.move_old and not self.move_new:
            screen.blit(self._new_surf, new_rect)
            screen.blit(self._old_surf, old_rect.move((self.posx, self.posy)))
        else:
            if self.move_old:
                screen.blit(self._old_surf, old_rect.move((self.posx, self.posy)))
            else:
                screen.blit(self._old_surf, old_rect)
            
            if self.move_new:
                screen.blit(self._new_surf, new_rect.move( \
                                    (self.posx - self.dir_x * new_rect.width, \
                                     self.posy - self.dir_y * new_rect.height)))
            else:
                screen.blit(self._new_surf, new_rect)
            
    def __str__(self):
        return "%s(%s, %s, (%s, %s), %s, %s)" % (self.__class__.__name__, 
                                                    self.duration, 
                                                    self.distance, 
                                                    self.dir_x, 
                                                    self.dir_y, 
                                                    self.move_old, 
                                                    self.move_new)

# ------------------------------------------------------------------------------

class FadeOutEffect(pyknicpygame.pyknic.context.transitions.TransitionEffect):

    def __init__(self, duration): #, resolution):
        self.duration = duration
        self.current_time = duration
        self.surf = None
        self.alpha_value = 255

    def enter(self):
        self.alpha_value = 255
        self.current_time = self.duration

    def think(self, delta_time):
        self.alpha_value = int(255.0 * self.current_time / self.duration)
        self.alpha_value = 0 if self.alpha_value < 0 else self.alpha_value #max(0, self.alpha_value)
        self.alpha_value = 255 if self.alpha_value > 255 else self.alpha_value #min(255, self.alpha_value)

        self.current_time -= delta_time
        if self.current_time > 0:
            return False
        return True # done

    def draw(self, screen, old_context, new_context):
        if not self.surf:
            self.surf = screen.copy().convert_alpha()
        new_context.draw(screen)
        self.surf.fill((0, 0, 0, 0))
        old_context.draw(self.surf)
        self.surf.fill((255, 255, 255, self.alpha_value), None, pygame.BLEND_RGBA_MULT)
        screen.blit(self.surf, (0,0))

    def __str__(self):
        return "%s(%s)" % (self.__class__.__name__, self.duration)
